﻿namespace DotNetCommon
{
    using System;

    /// <summary>
    /// 提供用于实现<see cref="System.IEquatable{T}"/>的辅助类。
    /// </summary>
    /// <remarks>继承<see cref="Equatable{ThisAssembly}"/>的类只需要实现<see cref="Object.GetHashCode"/>方法就可以拥有<see cref="Object.Equals(object)"/>、<c>==</c>、<c>!=</c> 比较的能力</remarks>
    public abstract class Equatable<T> : IEquatable<T>
    {
        /// <summary>
        /// 提供对象的哈希码。
        /// </summary>
        /// <returns></returns>
        public abstract override int GetHashCode();

        /// <summary>
        /// 确定该对象是否等于<paramref name="other"/>。
        /// </summary>
        public virtual bool Equals(T other) => other is T notNull && notNull.GetHashCode() == GetHashCode();

        /// <summary>
        /// 确定该对象是否等于<paramref name="obj"/>。
        /// </summary>
        public override bool Equals(object obj) => obj is T other && Equals(other);

        /// <summary>
        /// 确定给定的<paramref name="left"/>是否等于<paramref name="right"/>。
        /// </summary>
        public static bool operator ==(Equatable<T> left, Equatable<T> right) => Equals(left, right);

        /// <summary>
        /// 确定给定的<paramref name="left"/>是否等于<paramref name="right"/>。
        /// </summary>
        public static bool operator !=(Equatable<T> left, Equatable<T> right) => !Equals(left, right);
    }
}